package cn.gs.reflect;

//Auto Property load and store
import cn.gs.serializable.serialize.SerializeController;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

// @author gs
public class PropertyTool extends Thread {

    public final static boolean DEBUGGING = Boolean.valueOf(System.getProperty("cn.gs.test"));

    static {
        Runtime.getRuntime().addShutdownHook(new PropertyTool());
    }
    static Set<Class> classes = new HashSet<Class>();
    static Properties prop;
    static String path = DEBUGGING ? "gs.test.properties" : "gs.properties";

    @Override
    public void run() {
        saveProperties();
    }

    public static void saveProperties() {
        OutputStream os = null;
        try {
            if (prop == null) {
                prop = new Properties();
            }
            for (Class clazz : classes) {
                store(clazz);
            }
            os = new FileOutputStream(path);
            prop.store(os, null);
        } catch (Throwable ex) {
            System.err.println(ex);
        } finally {
            try {
                os.close();
            } catch (Throwable ex) {
                System.err.println(ex);
            }
        }
    }

    private static void store(Class clazz) {
        for (Field h : clazz.getDeclaredFields()) {
            if (Modifier.isStatic(h.getModifiers())) {
                String path = clazz.getCanonicalName() + "." + h.getName();
                h.setAccessible(true);
                Object o = null;
                try {
                    o = h.get(null);
                    String value = SerializeController.staticToString(o);
                    prop.put(path, value);
                } catch (Throwable ex) {
                    System.err.println(ex);
                }
            }
        }
    }

    public static void loadProperties() {
        if (prop == null) {
            prop = new Properties();
            InputStream is = null;
            try {
                is = new FileInputStream(path);
                prop.load(is);
            } catch (Throwable ex) {
                System.err.println(ex);
            } finally {
                try {
                    is.close();
                } catch (Throwable ex) {
                    System.err.println(ex);
                }
            }
        }
    }

    public static void load(Class clazz) {
        loadProperties();
        for (Field h : clazz.getDeclaredFields()) {
            if (Modifier.isStatic(h.getModifiers())) {
                String path = clazz.getCanonicalName() + "." + h.getName();
                String value = prop.getProperty(path);
                if (null != value) {
                    Object o = SerializeController.staticToObject(value, h.getType());
                    if (o != null) {
                        try {
                            h.setAccessible(true);
                            h.set(null, o);
                        } catch (Throwable ex) {
                            System.err.println(ex);
                        }
                    }
                }
            }
        }
        classes.add(clazz);
    }
}
